【教程】STM32H743驱动RGB屏幕并移植LVGL v8.0 您所在的位置:网站首页 stm32h750 ltdc频率 【教程】STM32H743驱动RGB屏幕并移植LVGL v8.0

【教程】STM32H743驱动RGB屏幕并移植LVGL v8.0

2024-06-19 01:32| 来源: 网络整理| 查看: 265

硬件准备

正点原子H743开发板+7寸 RGB LCD显示屏 + SDRAM (注意RGB屏幕必须外扩显存)

软件准备

        STM32cubeMX 6.1.2 + Keil 5

创建cubeMX工程首先打开STM32cubeMX软件,选择 ACCESS TO MCU SELECTOR

进入MCU 选择界面选中 STM32H743 然后开始项目

进入STM32cubeMX工程配置界面

首先切换选项卡到 Project Manager,我们注意到软件标题栏有个 Untitled * ,带星号表示当前进行过的操作未保存,按下ctrl + s 可以保存。我们每次操作完都尽量按下保存,防止cubeMX卡死导致没保存工程。

首先填写项目名称,已经项目保存路径,工具链IDE 我们选择为 MDK-ARM (keil 5)。修改堆区和栈区空间大小为0x2000。因为后面要移植lvgl,默认的堆区大小是不够的,栈区我们也放大一点。

然后给我圈起来的地方打个√,这样配置的外设都会单独生成c和h文件,不会都挤在main.c里面。

然后我们切换到引脚配置界面,按下ctrl+S保存项目,这样标题栏的星号就消失了。

配置SDRAM

     一般的MCU接口屏,比如SPI屏,8080接口屏,IIC接口屏是可以不需要外置显存的。这些屏幕可以通过发送命令当方式告诉屏幕坐标,然后再发送对应的像素值。但是RGB接口屏没命令可以发,一般是告诉LTDC一个内存地址,由LTDC控制器去内存拿像素值不断去扫描刷新屏幕的。所以要用到SDRAM或者SRAM。我们这里用到的是 W9825G6KH 这颗SDRAM,容量32MByte。我们的屏幕是1024 * 600的,颜色格式RGB 565 ,所以需要 1024*600*2 = 1,228,800 字节 = 1200 K字节 内存作为 屏幕显存。

SDRAM原理图

首先在最左侧栏目选中FMC,然后选择SDRAM1,配置如下。如果你用的不是上面的原理图,则需要根据具体硬件连接配置。

然后是下面部分时序的配置,这个是在 W9825G6KH 数据手册里的。

GPIO settings 不用管,如果你用的是正点原子H743核心板。直接点右上角生成工程,然后打开就可以了。

这里我们打开 fmc.c 文件,然后将SDRAM的初始化代码加入到 我圈到的位置。SDRAM芯片内部是有寄存器的,我们要通过fmc接口去发送命令配置这些寄存器然后才可以使用。

需要插入在/* USER CODE BEGIN 0 */注释行和 /* USER CODE END 0 */ 之间的代码如下

extern SDRAM_HandleTypeDef hsdram1; #define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200) uint8_t SDRAM_Send_Cmd(uint8_t bankx,uint8_t cmd,uint8_t refresh,uint16_t regval) {    uint32_t target_bank=0;    FMC_SDRAM_CommandTypeDef Command;        if(bankx==0) target_bank=FMC_SDRAM_CMD_TARGET_BANK1;          else if(bankx==1) target_bank=FMC_SDRAM_CMD_TARGET_BANK2;      Command.CommandMode=cmd;                    Command.CommandTarget=target_bank;          Command.AutoRefreshNumber=refresh;          Command.ModeRegisterDefinition=regval;      if(HAL_SDRAM_SendCommand(&hsdram1,&Command,0XFFFF)==HAL_OK)    {        return 0;      }    else return 1;     } void SDRAM_Initialization_Sequence(void) { uint32_t temp=0;  SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0);  HAL_Delay(1);                                 SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_PALL,1,0);        SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0); temp=(uint32_t)SDRAM_MODEREG_BURST_LENGTH_1       | \              SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   | \              SDRAM_MODEREG_CAS_LATENCY_2           | \              SDRAM_MODEREG_OPERATING_MODE_STANDARD |  \              SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;  SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp); HAL_SDRAM_ProgramRefreshRate(&hsdram1,677); }

并在 MX_FMC_Init 中调用该初始化函数

编译并进入调试模式,我们在 main 中的while(1) 前面加个断点,运行到这里。然后在memory中访问 0XC0000000 地址,如果能看到一堆  FF ,就说明SDRAM 已经初始化成功了。如果是问号? 则说明初始化有问题,这样你就需要重新检查一下了。

然后我们提升下主频,这样就能更快的访问SDRAM了。只需要更改 1. 处的时钟到480Mhz 然后回车,然后其它三处红圈的频率会自动更改。由于我们配置了 SDRAM的频率是 HCLK /2 ,所以此时SDRAM的运行频率是 120Mhz。W9825G6KH -6 这款芯片最快是到166Mhz,懒得配置了。

重新点击右上方生成代码,如果我们没有关闭 MDK工程的话点击 Close就可以了。

切换会Keil 会提示 文件被外部修改,需要重新载入。我们全选 YES就可以了

重新下载程序,,然后进入仿真检查,SDRAM是否可以正确访问。此时SDRAM就算配置完毕。

RGB-LTDC配置

接下来进入屏幕的配置。打开LTDC 然后选择RGB565模式,下面的配置如下

还需要配置层,一般我们用一层就可以了。层的帧缓存起始地址就是我们的SDRAM访问起始地址0XC0000000

接下来要配置GPIO, 这里需要改的引脚比较多。我们按照 LTDC_B  LTDC_G LTDC_R的顺序修改。如果按照RGB的顺序修改你会发现有些引脚原本就被LTDC_B占了,如果你直接改cubeMX的 LTDC会自动关闭,再次打开你之前进行的操作就没了。(很坑)

需要改动的引脚如下

LTDC_B3  --> PG11 LTDC_B4  --> PI4 LTDC_B5  --> PI5 LTDC_B6  --> PI6 LTDC_B7  --> PI7 LTDC_G2  --> PH13 LTDC_G3  --> PH14 LTDC_G4  --> PH15 LTDC_G5  --> PI0 LTDC_G6  --> PI1 LTDC_R3  --> PH9 LTDC_R4  --> PH10 LTDC_R5  --> PH11 LTDC_R6  --> PH12

直接搜索引脚,然后选中对应功能就算完事了。

然后把所有引脚的输出速度调到Hign,默认是 Low和very LOW。如果你用的默认引脚配置,那么你的屏幕速度只能到30Mhz,而且还闪烁。这款屏幕是可以到51.2Mhz的。

根据原理图,还有个屏幕背光引脚 PB5,我们设置为推挽输出,默认是高电平就可以了。

再调整下LTDC主频,到51.2Mhz。设置PLL3锁相环的DIVR3 除频器到 /5就可以了。

重新生成代码,然后打开KEIL5,编写屏幕测试代码

测试代码

#include static uint16_t LCD_BUFFER[600][1024] __attribute__((at(0XC0000000))); while(1){ memset(LCD_BUFFER,0xFF,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0xAA,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0xD0,sizeof(LCD_BUFFER)); HAL_Delay(1000); memset(LCD_BUFFER,0x00,sizeof(LCD_BUFFER)); HAL_Delay(1000); }

声明一个 静态数组,并且固定到 0XC0000000 地址(SDRAM)。

下载代码并复位开发板应该可以看到屏幕在 白 --> 红 -->紫 -->黑 四种颜色进行切换。

至此屏幕的配置就算完成

LVGL 移植

打开lvgl官网  https://github.com/lvgl/lvgl  

下载lvgl源码,解压放到我们的项目文件夹中

进入lvgl-master文件夹,删除多余没用的文件,只剩下这些

修改lv_conf_template.h名称为 lv_conf.h

将examples文件夹内的porting文件夹复制到lvgl_cong.h 同级目录

进入porting文件夹修改lv_port_disp_template.h 和对应的c 文件名称

打开KEIL5 修改添加几个目录 LV_CORE  LV_PORT LV_DEMO,分别存放lvgl源代码,lvgl移植文件,lvgl 演示程序

将src 路径下所有c文件添加到LVGL_CORE ,注意是 递归添加(大概几百个文件。。。)

port里只添加 disp 的和 lv_conf.h 。这里我只演示移植显示,不移植触控

demo我们添加 demo/benchmark 下的文件,如果你想试试其它demo也可以都添加了

添加 lv-master 包含目录

在Define里添加个全局宏  LV_CONF_INCLUDE_SIMPLE  前面要有个英文逗号

打开lv_conf.h lv_port_disp.c  lv_port_disp.h三个文件,开头有个if 0 ,把0 改成1,我画圈的地方要注意。还有lv_port_disp.h 在lv_port_disp.c中的名称

然后编译一遍会有1个错误和五百多个警告。警告不用管,我们解决下这个错误。

就是找不到包含的文件,改成我圈起来的。被注释掉的包含是之前的。

还有lv_port_disp.h中的包含也要改

再次编译还有3错误

打开lv_port_disp.c 注意两个画圈的地方。

修改这三个画圈的地方

找到这个函数,添加这行代码。

回到main.c 添加两个头文件的包含

找到滴答定时器的中断入口,添加这两行代码。

打开lvgl_conf.h  LV_USE_DEMO_BENCHMARK 设置为1 ,才能用这个demo

再次回到 main 修改如下。其中第一个圈和第二个圈是固定的,以后就不要动了。中间的圈是启动演示程序,该程序会进行一个图形跑分测试。

编译然后下载程序,不出意外,会进行一个跑分程序

至此,所有移植就算完毕!!!

当然还可以通过 DMA2D 帮我们搬运像素。这样屏幕刷新会更快。

关于lvgl的学习请参考lvgl官方文档,这里只教大家搭建好学习环境。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有